package core;

import model.BasicBlockSlot;
import model.BlockType;
import model.Slot;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 * This is the player board class. This should be able handle
 * a request to switch two blocks, switch the blocks, and offer
 * up any resultant combos.
 * It should also keep track of its state to notify on end
 * conditions, and current level.
 *
 * @author Daniel A. Villa
 */
public class PlayerBoard {

    // The level of difficulty
    private int level;
    // The slots that represent the space on the game board
    private ArrayList<ArrayList<Slot>> slotList;
    // The list of slams that will be dropped on the board.
    public Queue<Slam> slamList;
    // The rows of the board. This should be reflected as the rows of the screen. This is used when checking end conditions.
    private int rows;
    private int columns;
    private Logger logger = Logger.getLogger(PlayerBoard.class);

    /**
     * By taking in an x, y index the game board will switch
     * the blocks on the board and spin any tasks, like sending
     * mud blocks to other players.
     *
     * @param index x, y to switch with x+1, y
     */
    public void switchIndex(int[] index) {
        Slot left = slotList.get(index[1]).get(index[0]);
        Slot right = slotList.get(index[1]).get(index[0] + 1);
        logger.debug("Left: " + left.getClass().getSimpleName() + " Right: " + right.getClass().getSimpleName());
        slotList.get(index[1]).set(index[0], right);
        slotList.get(index[1]).set(index[0] + 1, left);
    }

    /**
     * Constructor for the game board.
     *
     * @param level
     */
    public PlayerBoard(int level, int rows, int columns) {
        this.rows = rows;
        this.columns = columns;
        this.level = level;
        slamList = new PriorityQueue<Slam>();
        init();
    }

    /**
     * For now we will just fill up our not already defined slots.
     */
    private void init() {
        if (slotList == null) {
            slotList = new ArrayList<ArrayList<Slot>>();
        }
        for (int i = 0; i < rows; i++) {
            ArrayList<Slot> slotRow = new ArrayList<Slot>();
            for (int j = 0; j < columns; j++) {
                slotRow.add(new BasicBlockSlot(BlockType.BLANK));
            }
            slotList.add(slotRow);
        }
    }

    /**
     * When the game board is breaking down a block, the board
     * should pause to allow the player to react to the mud block
     * being broken.
     */
    public void pause() {
    }

    /**
     * Should continue the ticker, checking for end conditions.
     */
    public void play() {
    }

    /**
     * Not sure if this is needed yet.
     *
     * @return
     */
    public double timeToNextRow() {
        return 0.0;
    }

    /**
     * Should add the slam to the queue.
     */
    public void addMud(Slam slam) {
    }

    /**
     * Represents a game "tick" This should move all the blocks up
     * on the screen allowing new rows to be added from the bottom
     * and should also check end conditions of the board is full.
     */
    public void tick() {
    }

    /**
     * Will notify any listeners if important things have changed. I.E.
     * if a slam should be sent, if the game is over, etc.
     */
    public void notifyEvents() {
    }

    public int getRows() {
        return rows;
    }

    public int getColumns() {
        return columns;
    }

    public Slot getSlot(int row, int column) {
        return slotList.get(row).get(column);
    }

    /**
     * Will update the slot with the given object.
     *
     * @param row
     * @param column
     * @param slot
     * @return
     */
    public boolean setSlot(int row, int column, Slot slot) {
        Slot s = slotList.get(row).set(column, slot);
        return true;
    }
}